//
//  ViewController.m
//  ThreadTest
//
//  Created by YaoZhaofeng on 16/6/8.
//  Copyright © 2016年 YaoZhaofeng. All rights reserved.
//

#import "ViewController.h"
#import "CategoryObject.h"

@interface ViewController () {
    dispatch_source_t alert_time_source;
    BOOL isAlertSuspend;
    dispatch_queue_t bgQueue;
    NSThread *myThread;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    isAlertSuspend = YES;
    bgQueue = dispatch_queue_create("messageServicebgQueue", DISPATCH_QUEUE_SERIAL);
//    [self testDispatchGroup];
    
//    [self syncThread];
    myThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadSelector:) object:nil];
    [myThread start];
    [self performSelector:@selector(threadTest) onThread:myThread withObject:nil waitUntilDone:NO];
}

- (void)threadSelector:(id)object {
    NSLog(@"");
}

- (void)threadTest {
    NSLog(@"");
}

- (void)syncThread {
    NSLog(@"currentThread::%@", [NSThread currentThread]);
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"currentThread::%@", [NSThread currentThread]);
        
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"currentThread::%@", [NSThread currentThread]);
    });
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/**
 *dispatch_sync不会切换线程
 */
- (void)syncThreadTest {
    dispatch_async(bgQueue, ^{
        for (int i = 0; i <= 10000; i++) {
            NSLog(@"i::%i", i);
        }
    });
    dispatch_sync(bgQueue, ^{
        NSLog(@"同步执行");
    });
    NSLog(@"done!!!");

}
 /*疑问，在dispatch_barrier_sync前面使用for循环添加100个任务，发现dispatch_barrier_sync中的任务并没有在前100个执行完之后执行，而是提前了。
 *
 */
- (void)api_dispatch_barrier {
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    for (int i = 0; i < 100; i++) {
        __block int j = i;
        dispatch_async(queue, ^{
            NSLog(@"读任务%d", j);
        });
    }
    
    dispatch_barrier_async(queue, ^{
        NSLog(@"写操作1");
    });
    NSLog(@"dispatch_barrier_async...");
    
    dispatch_barrier_sync(queue, ^{
        NSLog(@"写操作2");
    });
    NSLog(@"dispatch_barrier_sync...");
    
    for (int i = 100; i < 200; i++) {
        __block int j = i;
        dispatch_async(queue, ^{
            NSLog(@"读任务%d", j);
        });
    }
}

/**
 *设置queue1的target设置为queue2之后，再使用dispatch_get_specific，结果如下：
 *对于queue1：可以使用queue1Tag或者queue2Tag进行获取，如果没有设置queue1Tag，可以使用queue2Tag获取
 *对于queue2：只能使用queue2Tag获取
 *
 */
- (void)api_dispatch_get_specific {
    void *queue1Tag = &queue1Tag;
    dispatch_queue_t queue1 = dispatch_queue_create("com.xy.queue1", NULL);
    dispatch_queue_set_specific(queue1, queue1Tag, queue1Tag, NULL);
    
    void *queue2Tag = &queue2Tag;
    dispatch_queue_t queue2 = dispatch_queue_create("com.xy.queue2", NULL);
    dispatch_queue_set_specific(queue2, queue2Tag, queue2Tag, NULL);
    
    dispatch_sync(queue1, ^{
        NSLog(@"\n\t\n\t线程：queue1 开始\n\t");
        if (dispatch_get_specific(queue1Tag)) {
            NSLog(@"设置target之前，从queue1Tag获取的的肯定是当前queue");
        }
        NSLog(@"\n\t线程：queue1 结束\n\t\n\t\n\t");
    });
    
    dispatch_set_target_queue(queue1, queue2);
    
    dispatch_sync(queue1, ^{
         NSLog(@"\n\t\n\t线程：queue1 开始\n\t");
        if (dispatch_get_specific(queue1Tag)) {
            NSLog(@"设置target之后，从queue1Tag获取的的 是 当前queue");
        } else {
            NSLog(@"设置target之后，从queue1Tag获取的的 不是 当前queue");
        }
        if (dispatch_get_specific(queue2Tag)) {
            NSLog(@"设置target之后，从queue2Tag获取的的 是 当前queue");
        } else {
            NSLog(@"设置target之后，从queue2Tag获取的的 不是 当前queue");
        }
        NSLog(@"\n\t线程：queue1 结束\n\t\n\t\n\t");
    });
    
    dispatch_sync(queue2, ^{
        NSLog(@"\n\t\n\t线程：queue2 开始\n\t");
        if (dispatch_get_specific(queue1Tag)) {
            NSLog(@"设置target之后，从queue1Tag获取的的 是 当前queue");
        } else {
            NSLog(@"设置target之后，从queue1Tag获取的的 不是 当前queue");
        }
        if (dispatch_get_specific(queue2Tag)) {
            NSLog(@"设置target之后，从queue2Tag获取的的 是 当前queue");
        } else {
            NSLog(@"设置target之后，从queue2Tag获取的的 不是 当前queue");
        }
        NSLog(@"\n\t线程：queue2 结束\n\t\n\t");
    });
}

- (void)testDispatchGroup {
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"blk0");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"blk1");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"blk2");
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"blk3");
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"blk4");
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"done");
    });
    
    for (int i = 5; i < 1000; i++) {
        dispatch_group_async(group, queue, ^{
            NSLog(@"blk%d",i);
        });
    }
    
}

/**
 *  结论：makeObjectsPerformSelector和遍历数组对每个对象执行方法效果一样，在同一个线程按顺序执行
 */
- (void)testSystemApi{
    NSMutableArray *array = [NSMutableArray array];
    for (int i = 0; i<100; i++) {
        CategoryObject *object = [[CategoryObject alloc] initWithId:@(i)];
        [array addObject:object];
    }
    [array makeObjectsPerformSelector:@selector(doSomething)];
}

/**
 *  结论：在不同线程中往字典添加和删除元素，只要key不同，不会crash
 */
- (void)testMutDictionaryInMutThread{
    NSMutableDictionary *tempDic = [NSMutableDictionary dictionary];
    
    for (int i = 0; i<100; i++) {
        [tempDic setObject:@(i) forKey:[NSString stringWithFormat:@"%d",i]];
    }
    
    __block int i = 100;
    dispatch_queue_t queue1 = dispatch_queue_create("1111", NULL);
    dispatch_async(queue1, ^{
        while (true) {
            NSLog(@"set value for key:: %i",i);
            [tempDic setObject:@(i) forKey:[NSString stringWithFormat:@"%d",i]];
            i++;
        }
    });
    
    dispatch_queue_t queue2 = dispatch_queue_create("2222", NULL);
    __block int j = 0;
    dispatch_async(queue2, ^{
        while (true) {
            NSLog(@"remove value for key:: %i",j);
            [tempDic removeObjectForKey:[NSString stringWithFormat:@"%d",j]];
            j++;
        }
    });
}

- (void)testDispatchSource {
    dispatch_queue_t queue = dispatch_queue_create("tt", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        int i = 0;
        while (true) {
            [self dispatchSource:i];
            i++;
        }
//        for (int i = 0; i < MAXFLOAT; i ++) {
//            [self dispatchSource:i];
//            //        sleep(.4);
//        }
    });
    
}

- (void)dispatchSource:(int)i {
    if (!alert_time_source){
        alert_time_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, bgQueue);
    }
    dispatch_source_set_event_handler(alert_time_source, ^{ @autoreleasepool {
//        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"i == %d",i);
//        });
//        dispatch_source_set_event_handler(alert_time_source, ^{ @autoreleasepool {
            dispatch_suspend(alert_time_source);
            isAlertSuspend = YES;
            NSLog(@"alert_time_source suspend");
//        }});
        
    }});
    if(isAlertSuspend) {
        uint64_t interval = (1 * NSEC_PER_SEC);
        dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, interval);
        
        dispatch_source_set_timer(alert_time_source, tt, 0, 0.0);
        dispatch_resume(alert_time_source);
        isAlertSuspend = NO;
        NSLog(@"alert_time_source resume");
    }
}

- (IBAction)btnClick:(id)sender {
}
@end
